/*==============================================================================
            Copyright (c) 2013 Moritz Hader, Marcel Schrder
            All Rights Reserved.

	@file  ShaderManagementUnit.h

	@brief This header provides the class-definitions as well as the shaders
	used by the ShaderManagementUnit. General purpose of this class is to provide
	an easy to use interface to initialize, load and use GLSL programs.
   
   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
==============================================================================*/

#ifndef _SHADERMANAGEMENTUNIT_LIBRARY__
#define _SHADERMANAGEMENTUNIT_LIBRARY__

#include <GLES2/gl2.h>
#include <egl/HeimdallMath.h>


/*
 * The following enums define the indices used to acces attributes and uniforms within the array that
 * holds the handles to the attributes, uniformas and to the shader-programs itself.
 */
enum HDProgramTypes { HD_SHADER_UNIFORM_COLOR = 0, HD_SHADER_PRIMITIVE_SHADING, HD_SHADER_POINT_LIGHT, HD_SHADER_TEXTURE, HD_SHADER_ENDLIST};
enum HDAttributeTypes { HD_ATTRIBUTES_VERTEX = 0, HD_ATTRIBUTES_COLOR, HD_ATTRIBUTES_NORMAL, HD_ATTRIBUTES_TEXTURE, HD_ATTRIBUTES_ENDLIST};


class ShaderManagementUnit{

public:
	ShaderManagementUnit();
	~ShaderManagementUnit();

	void LoadShader(HDProgramTypes shaderProgIndex, const char* vertexShader, const char* fragmentShader,...);
	void PrepareShaders(HDProgramTypes shaderProgIndex,...);

	GLuint shaderHandles[HD_SHADER_ENDLIST]; //By using the HD_SHADER_ENDLIST, the size of the array will allways vary with the amount of shaders
};





//Define some of the stock-shaders

//Vertex and Fragment-Shader to draw vertices with one uniform color.
	static const char* HD_VERTEXSHADER_UNIFORM_COLOR = 	"attribute vec4 HVertex;"
														"uniform mat4 HMvp;"
														"void main(void){"
														"gl_Position = HMvp * HVertex;"
														"}";

	static const char* HD_FRAGMENTSHADER_UNIFORM_COLOR = "precision mediump float;"
														"uniform vec4 HColor;"
														"void main(void){"
														"gl_FragColor = HColor;"
														"}";


//Vertex and Fragment-Shader to draw fragments with diffuse lightning (3 colors per fragment)
	static const char* HD_VERTEXSHADER_PRIMITIVE_SHADING = 	"attribute vec4 HVertex;"
															"attribute vec4 HColor;"
															"uniform mat4 HMvp;"
															"varying vec4 HFragColor;"
															"void main(void){"
															"HFragColor=HColor;"
															"gl_Position = HMvp * HVertex;"
															"}";

	static const char* HD_FRAGMENTSHADER_PRIMITIVE_SHADING = "precision mediump float;"
															"varying vec4 HFragColor;"
															"void main(void){"
															"gl_FragColor = HFragColor;"
															"}";

//Vertex and Fragment-Shader to draw fragments with diffuse calculated by a point ligth
	static const char* HD_VERTEXSHADER_POINT_LIGHT = 	"attribute vec4 HVertex;"
														"attribute vec3 HNormal;"
														"uniform vec4 HColor;"
														"uniform mat4 HMvM;"
														"uniform mat4 HMvp;"
														"uniform vec3 HLightSpot;"
														"varying vec4 HFragColor;"
														"void main(void){"
															"mat3 NormalmvM;"
															"vec3 NormalVec;"
															"vec4 Vertex4D;"
															"vec3 Vertex3D;"
															"vec3 LightRay;"
															"NormalmvM[0]=normalize(HMvM[0].xyz);"
															"NormalmvM[1]=normalize(HMvM[1].xyz);"
															"NormalmvM[2]=normalize(HMvM[2].xyz);"
															"NormalVec=normalize(NormalmvM*HNormal);"
															"Vertex4D=HMvM*HVertex;"
															"Vertex3D=Vertex4D.xyz/Vertex4D.w;"
															"LightRay=normalize(HLightSpot-Vertex3D);"
															"HFragColor.xyz=HColor.xyz*max(dot(NormalVec,LightRay),0.0);"
															"HFragColor.w=HColor.w;"
															"gl_Position = HMvp * HVertex;"
														"}";


	static const char* HD_FRAGMENTSHADER_POINT_LIGHT = "precision mediump float;"
														"varying vec4 HFragColor;"
														"void main(void){"
														"gl_FragColor = HFragColor;"
														"}";
#endif
